package cc.linker.steplink.crm.merchant.service;

import cc.linker.steplink.crm.merchant.dao.NewMallDao;
import cc.linker.steplink.crm.response.GlobalException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class GoodsDataService {

    @Autowired
    private NewMallDao newMallDao;

    private static final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public Object listGoodsData(Map<String, Object> param) {
        Integer pageIndex = (Integer) param.get("pageIndex");
        Integer pageSize = (Integer) param.get("pageSize");
        Integer order = (Integer) param.get("order");
        String sort = (String) param.get("sort");
        if(StringUtils.isEmpty(param.get("groupId"))){
            param.put("groupId",null);
        }

        if (!StringUtils.isEmpty(order) && !StringUtils.isEmpty(sort)) {
            String orderBy;
            switch (order) {
                case 1:
                    // 浏览次数
                    orderBy = "viewNum";
                    break;
                case 2:
                    // 访问人数
                    orderBy = "guestNum";
                    break;
                case 3:
                    // 人均浏览次数
                    orderBy = "viewGuestNum";
                    break;
                case 4:
                    // 分享次数
                    orderBy = "shareNum";
                    break;
                case 5:
                    // 加购人数
                    orderBy = "addNum";
                    break;
                case 6:
                    // 支付人数
                    orderBy = "payNum";
                    break;
                case 7:
                    // 访问支付转化率
                    orderBy = "conversion";
                    break;
                case 8:
                    // 成交单数
                    orderBy = "dealNum";
                    break;
                case 9:
                    // 客单价
                    orderBy = "guestPay";
                    break;
                default:
                    throw GlobalException.build("order参数不正确");
            }
            param.put("orderBy", orderBy);
            param.put("sort", sort);
        } else {
            param.put("orderBy", "viewNum");
            param.put("sort", "desc");
        }
        PageHelper.startPage(pageIndex, pageSize);
        List<Map<String, Object>> maps = newMallDao.listGoodsData(param);
        maps.forEach(x->{
            x.put("conversion",x.get("conversion").toString()+"%");
        });
        return new PageInfo<>(maps);
    }

    public Map<String, Object> getGoodsDataByGoodsId(String goodsId) {
        Map<String, Object> param = new HashMap<>();
        param.put("goodsId", goodsId);
        Map<String, Object> goodsData = newMallDao.getGoodsDataByGoodsId(param);
        if (goodsData == null) {
            goodsData = new HashMap<>();
            goodsData.put("goodsId", "0");
            goodsData.put("viewNum", "0");
            goodsData.put("viewGuestNum", "0");
            goodsData.put("shareNum", "0");
            goodsData.put("addNum", "0");
            goodsData.put("payNum", "0");
            goodsData.put("dealNum", "0");
            goodsData.put("addGoodsNum", "0");
            goodsData.put("addTimes", "0");
            goodsData.put("guestNum", "0");
            goodsData.put("conversion", "0.00");
            goodsData.put("payGoodsNum", "0");
            goodsData.put("payAmount", "0.00");
            goodsData.put("guestPay", "0.00");
        }
        String conversion = goodsData.get("conversion").toString() + "%";
        goodsData.put("conversion", conversion);
        return goodsData;
    }

    public List<Map<String, Object>> getGoodsDataByGoodsIdAndType(Map<String, Object> param) {
        Integer type = (Integer) param.get("type");
        String row = this.getRowNameByType(type);
        param.put("row", row);
        String startTime = (String) param.get("startTime");
        String endTime = (String) param.get("endTime");
        int diff;
        if (StringUtils.isEmpty(startTime) && StringUtils.isEmpty(endTime)) {
            diff = 30;
            endTime = df.format(LocalDate.now());
            startTime = df.format(LocalDate.now().minusDays(diff));
            param.put("startTime", startTime);
            param.put("endTime", endTime);
        } else {
            LocalDate start;
            LocalDate end;
            try {
                start = LocalDate.parse(startTime, df);
                end = LocalDate.parse(endTime, df);
            } catch (Exception e) {
                throw GlobalException.build("参数错误");
            }
            if (start.isAfter(end)) {
                throw GlobalException.build("开始时间不能大于结束时间");
            }
            diff = (int) ChronoUnit.DAYS.between(start, end);

            long betweenNow = ChronoUnit.DAYS.between(start, end);
            if (betweenNow > 366) {
                throw GlobalException.build("最多可选择1年内数据");
            }
        }
        List<String> dateList = new ArrayList<>();
        LocalDate parse = LocalDate.parse(startTime, df);
        for (int i = 0; i <= diff; i++) {
            String format = df.format(parse.plusDays(i));
            dateList.add(format);
        }
        List<Map<String, Object>> goodsDataList = newMallDao.getGoodsDataByGoodsIdAndType(param);
        for (Map<String, Object> map : goodsDataList) {
            String date = map.get("date").toString();
            dateList.remove(date);
        }
        for (String s : dateList) {
            Map<String, Object> map = new HashMap<>();
            map.put("date", s);
            map.put("num", 0);
            goodsDataList.add(map);
        }
        goodsDataList = goodsDataList.stream()
                .sorted(this::compareLocalDate)
                .collect(Collectors.toList());
        return goodsDataList;
    }

    public Object listEnrollData(Map<String, Object> param) {
        Integer pageIndex = (Integer) param.get("pageIndex");
        Integer pageSize = (Integer) param.get("pageSize");
        Integer order = (Integer) param.get("order");
        String sort = (String) param.get("sort");
        if (!StringUtils.isEmpty(order) && !StringUtils.isEmpty(sort)) {
            String orderBy;
            switch (order) {
                case 1:
                    // 浏览次数
                    orderBy = "viewNum";
                    break;
                case 2:
                    // 访问人数
                    orderBy = "guestNum";
                    break;
                case 3:
                    // 人均浏览次数
                    orderBy = "viewGuestNum";
                    break;
                case 4:
                    // 分享次数
                    orderBy = "shareNum";
                    break;
                case 5:
                    // 支付人数
                    orderBy = "payNum";
                    break;
                case 6:
                    // 访问支付转化率
                    orderBy = "conversion";
                    break;
                case 7:
                    // 客单价
                    orderBy = "guestPay";
                    break;
                default:
                    throw GlobalException.build("order参数不正确");
            }
            param.put("orderBy", orderBy);
            param.put("sort", sort);
        } else {
            param.put("orderBy", "viewNum");
            param.put("sort", "desc");
        }
        PageHelper.startPage(pageIndex, pageSize);
        List<Map<String, Object>> maps = newMallDao.listEnrollData(param);
        maps.forEach(x->{
            x.put("conversion",x.get("conversion").toString()+"%");
        });
        return new PageInfo<>(maps);
    }

    public Map<String, Object> getEnrollDataByEnrollId(String enrollId) {
        Map<String, Object> param = new HashMap<>();
        param.put("enrollId", enrollId);
        Map<String, Object> enrollData = newMallDao.getEnrollDataByEnrollId(param);
        if (enrollData == null) {
            enrollData = new HashMap<>();
            enrollData.put("enrollId", "0");
            enrollData.put("viewNum", "0");
            enrollData.put("viewGuestNum", "0");
            enrollData.put("shareNum", "0");
            enrollData.put("payNum", "0");
            enrollData.put("guestNum", "0");
            enrollData.put("conversion", "0.00");
            enrollData.put("payAmount", "0.00");
            enrollData.put("guestPay", "0.00");
        }
        String conversion = enrollData.get("conversion").toString() + "%";
        enrollData.put("conversion", conversion);
        return enrollData;
    }

    public List<Map<String, Object>> getEnrollDataByEnrollIdAndType(Map<String, Object> param) {
        Integer type = (Integer) param.get("type");
        String row = this.getRowNameByType(type);
        param.put("row", row);
        String startTime = (String) param.get("startTime");
        String endTime = (String) param.get("endTime");
        int diff;
        if (StringUtils.isEmpty(startTime) && StringUtils.isEmpty(endTime)) {
            diff = 30;
            endTime = df.format(LocalDate.now());
            startTime = df.format(LocalDate.now().minusDays(diff));
            param.put("startTime", startTime);
            param.put("endTime", endTime);
        } else {
            LocalDate start;
            LocalDate end;
            try {
                start = LocalDate.parse(startTime, df);
                end = LocalDate.parse(endTime, df);
            } catch (Exception e) {
                throw GlobalException.build("参数错误");
            }
            if (start.isAfter(end)) {
                throw GlobalException.build("开始时间不能大于结束时间");
            }
            diff = (int) ChronoUnit.DAYS.between(start, end);

            long betweenNow = ChronoUnit.DAYS.between(start, end);
            if (betweenNow > 366) {
                throw GlobalException.build("最多可选择1年内数据");
            }
        }
        List<String> dateList = new ArrayList<>();
        LocalDate parse = LocalDate.parse(startTime, df);
        for (int i = 0; i <= diff; i++) {
            String format = df.format(parse.plusDays(i));
            dateList.add(format);
        }
        List<Map<String, Object>> enrollDataList = newMallDao.getEnrollDataByEnrollIdAndType(param);
        for (Map<String, Object> map : enrollDataList) {
            String date = map.get("date").toString();
            dateList.remove(date);
        }
        for (String s : dateList) {
            Map<String, Object> map = new HashMap<>();
            map.put("date", s);
            map.put("num", 0);
            enrollDataList.add(map);
        }
        enrollDataList = enrollDataList.stream()
                .sorted(this::compareLocalDate)
                .collect(Collectors.toList());
        return enrollDataList;
    }


    private int compareLocalDate(Map a, Map b) {
        String date1 = (String) a.get("date");
        String date2 = (String) b.get("date");
        LocalDate parse1 = LocalDate.parse(date1, df);
        LocalDate parse2 = LocalDate.parse(date2, df);
        if (parse1.isAfter(parse2)) {
            return 1;
        } else if (parse1.equals(parse2)) {
            return 0;
        } else {
            return -1;
        }
    }

    private String getRowNameByType(Integer type) {
        String row;
        switch (type) {
            case 1:
                row = "VIEW_NUM";
                break;
            case 2:
                row = "ADD_NUM";
                break;
            case 3:
                row = "PAY_NUM";
                break;
            case 4:
                row = "DEAL_NUM";
                break;
            case 5:
                row = "ADD_GOODS_NUM";
                break;
            case 6:
                row = "GUEST_NUM";
                break;
            case 7:
                row = "PAY_GOODS_NUM";
                break;
            case 8:
                row = "ADD_TIMES";
                break;
            case 9:
                row = "PAY_AMOUNT";
                break;
            default:
                row = "PAY_GOODS_NUM";
                break;
        }
        return row;
    }
}
